package cn.kilo.domain.service.pay.impl;


import cn.kilo.domain.model.pay.req.WeChatPayRequest;
import cn.kilo.domain.repository.IStrategyRepository;
import cn.kilo.domain.service.pay.IWxChatPayService;
import cn.kilo.domain.support.HttpUtils;
import cn.kilo.domain.support.WeChatPayCallBackValidator;
import cn.kilo.domain.support.WeChatPayConfig;
import cn.kilo.domain.support.WeChatSupport;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.java.service.payments.h5.H5Service;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author kilok
 * 微信支付服务
 */

@Component("WXPayService")
@Slf4j

public class WeChatPayService implements IWxChatPayService {

    @Resource
    private WeChatPayConfig weChatPayConfig;

    @Resource
    private WeChatPayRequest weChatPayRequest;

    @Resource
    private IStrategyRepository repository;

    @Resource
    private WeChatSupport weChatSupport;

    private final ReentrantLock lock = new ReentrantLock();

    private Verifier verifier;

    private CertificatesManager certificatesManager;

    @Override
    public String H5Pay(Integer price, String orderId, String ip) {
        log.info("开始预支付");
        return weChatSupport.prePay(orderId,price,ip);
    }

    @Override
    public Map<String, String> callBack(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
        log.info("支付回调");

        //处理通知参数
        Map<String,Object> bodyMap=getCallBackBody(httpServletRequest);

        if(null==bodyMap){
            return falseMsg(httpServletResponse);
        }

        if(lock.tryLock()){
            try{

                //解密
                String resource=bodyMap.get("resource").toString();
                Map<String,Object> resourcedMap= WeChatPayCallBackValidator.decryptFromResource(resource,weChatPayConfig.getAPI_V3_KEY(),1);

                //订单id
                String orderNo=resourcedMap.get("out_trade_no").toString();

                String transactionId=resourcedMap.get("transaction_id").toString();

                //对获取的订单号进行处理
                Long orderId=Long.parseLong(orderNo);
                repository.setOrderPayEd(orderId);
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(e);
            } finally {
                //释放锁
                lock.unlock();
            }
        }
        //成功应答
        return successMsg(httpServletResponse);
    }

    /**
     * 查询订单
     *
     * @param orderNo
     * @return
     */
    @Override
    public HashMap<String, Transaction> getPayInfo(String orderNo) {
        Transaction orderInfo = weChatSupport.getOrderInfo(orderNo, weChatPayConfig.getMCH_ID());
        HashMap<String,Transaction> res=new HashMap<>();
        res.put("订单信息",orderInfo);
        return res;
    }

    @Override
    public void closeOrder(String orderId) {
        weChatSupport.closeOrder(orderId,weChatPayConfig.getMCH_ID());
    }

    @Override
    public void getPay() {
        HashMap<String,Object> map=new HashMap<>();

    }

    private Map<String,Object>  getCallBackBody(HttpServletRequest request) throws IOException {
        //处理通知参数
        String body= HttpUtils.readDate(request);
        log.info("回调参数:{}",body);

        //转化为map
        Map<String,Object> bodyMap= JSONObject.parseObject(body, new TypeReference<Map<String, Object>>() {});

        //微信的通知id，唯一id

        String callBackId=bodyMap.get("id").toString();

        //验证签名信息
        WeChatPayCallBackValidator weChatPayCallBackValidator
                = new WeChatPayCallBackValidator(verifier,callBackId,body);
        if(!weChatPayCallBackValidator.validate(request)){
            log.error("通知验签失败");
            return null;
        }
        log.info("通知验签成功");

        return bodyMap;
    }
    private Map<String,String> falseMsg(HttpServletResponse response){
        Map<String,String> resMap=new HashMap<>(0);

        //失败应答
        response.setStatus(500);
        resMap.put("code","ERROR");
        resMap.put("message","通知验签失败");
        return resMap;
    }

    private Map<String,String> successMsg(HttpServletResponse response){
        Map<String,String> resMap=new HashMap<>(0);
        //成功应答
        response.setStatus(200);
        resMap.put("code","SUCCESS");
        resMap.put("message","成功");
        return resMap;
    }
}
